﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace TDesktop
{
    internal partial class CommonToolkit
    {
        internal static class KeyboardWrap
        {
            /// <summary>
            /// （钩子监控到键盘操作时发出的）HookKeyboard事件对应的委托
            /// </summary>
            internal delegate IntPtr HookKeyboardEventHandler(Int32 code, KeyMessage message, KBDLLHOOKSTRUCT param);

            /// <summary>
            /// 设置Window钩子的回调函数委托
            /// </summary>
            private delegate IntPtr HookKeyboardDelegate(Int32 code, IntPtr wParam, IntPtr lParam);
            private static HookKeyboardDelegate m_hookKeyboardProc;
            private static IntPtr m_hookKeyboardHandle;

            private static Keys[] m_keys;

            
            internal static Keys[] AllKeys
            {
                get
                {
                    if (m_keys == null)
                    {
                        List<Keys> keys = new List<Keys>();
                        foreach (Int32 i in Enum.GetValues(typeof(Keys)))
                        {
                            keys.Add((Keys)i);
                        }
                        m_keys = keys.ToArray();
                    }
                    return m_keys;
                }
            }

            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            private static extern IntPtr SetWindowsHookEx(Int32 idHook, HookKeyboardDelegate lpfn, IntPtr hMod, Int32 dwThreadId);

            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            private static extern Boolean UnhookWindowsHookEx(IntPtr hhk);

            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            private static extern IntPtr CallNextHookEx(IntPtr hhk, Int32 nCode, IntPtr wParam, IntPtr lParam);

            /// <summary>
            /// 注册键盘监控
            /// </summary>
            internal static void HookWindowsHookEx()
            {
                m_hookKeyboardProc = new HookKeyboardDelegate(HookKeyboardProc);
                IntPtr handle = Process.GetCurrentProcess().MainModule.BaseAddress;
                m_hookKeyboardHandle = SetWindowsHookEx((Int32)HookType.WH_KEYBOARD_LL, m_hookKeyboardProc, handle, 0);
            }

            /// <summary>
            /// 反注册键盘监控
            /// </summary>
            internal static void UnhookWindowsHookEx()
            {
                UnhookWindowsHookEx(m_hookKeyboardHandle);
            }

            /// <summary>
            /// 根据Keys枚举成员的字符串表示，转换得到Keys枚举
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            internal static Keys GetKeysByName(String name)
            {
                Keys result = Keys.None;
                if (name.ToLower().Equals(Properties.CoreResources.String_ShortCut_Ctrl.ToLower()))
                {
                    result = Keys.Control;
                }
                else
                {
                    foreach (Keys key in AllKeys)
                    {
                        if (key.ToString().Equals(name))
                        {
                            result = key;
                            break;
                        }
                    }
                }
                return result;
            }

            /// <summary>
            /// 键盘监控回调函数，里面激活键盘事件
            /// </summary>
            /// <param name="code"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            private static IntPtr HookKeyboardProc(Int32 code, IntPtr wParam, IntPtr lParam)
            {
                if (HookKeyboard != null && code >= 0)
                {
                    KBDLLHOOKSTRUCT param = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
                    HookKeyboard(code, (KeyMessage)wParam, param);
                }

                return CallNextHookEx(m_hookKeyboardHandle, code, wParam, lParam);
            }

            /// <summary>
            /// 钩子监控到键盘操作时触发
            /// </summary>
            internal static event HookKeyboardEventHandler HookKeyboard;

            /// <summary>
            /// 钩子类型
            /// </summary>
            private enum HookType
            {
                WH_KEYBOARD_LL = 13,
                WH_MOUSE_LL = 14,
            };
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    /// <summary>
    /// 键盘钩子回调函数的参数类
    /// </summary>
    internal class KBDLLHOOKSTRUCT
    {
        public Int32 vkCode;
        public Int32 scanCode;
        public Int32 flags;
        public Int32 time;
        public Int32 dwExtraInfo;
    };
}
